<template>
  <Transition
    @before-enter="onBeforeEnter"
    @enter="onEnter"
    @after-enter="onAfterEnter"
    @enter-cancelled="onEnterCancelled"
    @before-leave="onBeforeLeave"
    @leave="onLeave"
    @after-leave="onAfterLeave"
    @leave-cancelled="onLeaveCancelled"
    :css="false"
    ref="transItem"
    v-show="showAnim"
  >
      <slot></slot> <!-- 向内传递插槽内容 -->
  </Transition>
</template>
<script setup lang="ts">
import { ref,onMounted,shallowRef,getCurrentInstance } from 'vue'
import { animate,easeInOut, easeIn, easeOut, cubicBezier } from "motion"
import { useSceneStore } from '@/stores/scene';
import { componentTypes, mittTypes } from '@/util/types';
const { appContext : { config: { globalProperties } } } = getCurrentInstance();

const internalInstance = getCurrentInstance()
const emitter = internalInstance.appContext.config.globalProperties.emitter
const sceneStore = useSceneStore()
// 缓动类型映射
const easingFunctions = {
    "easeInOut": easeInOut,
    "easeIn": easeIn,
    "easeOut": easeOut,
    "customBezier": cubicBezier(0.25, 0.1, 0.25, 1),
    "linear": (progress) => progress // 线性插值，进度直接等于进度
};
const props = defineProps({
  timelineData:{
    type: Object,
    default: null
  },
  showAnim:{
    type: Boolean,
    default: false
  }
})
const transItem = ref()
const slotItemRef = shallowRef(null)
const showAnim = ref(props.showAnim)
// 在元素被插入到 DOM 之前被调用
// 用这个来设置元素的 "enter-from" 状态
function onBeforeEnter(el) {}

// 在元素被插入到 DOM 之后的下一帧被调用
// 用这个来开始进入动画
function onEnter(el, done) {
  // if(props.animation){
  //     const sequence = [] as any
  //     props.animation.forEach(element => {
  //         sequence.push([el,element.animAttri,element.animOption])
  //     });
  //     animate(sequence,props.animationOption)
  // }
  
// 调用回调函数 done 表示过渡结束
// 如果与 CSS 结合使用，则这个回调是可选参数
done()
}

// 当进入过渡完成时调用。
function onAfterEnter(el) {}

// 当进入过渡在完成之前被取消时调用
function onEnterCancelled(el) {}

// 在 leave 钩子之前调用
// 大多数时候，你应该只会用到 leave 钩子
function onBeforeLeave(el) {}

// 在离开过渡开始时调用
// 用这个来开始离开动画
function onLeave(el, done) {
// 调用回调函数 done 表示过渡结束
// 如果与 CSS 结合使用，则这个回调是可选参数
done()
}

// 在离开过渡完成、
// 且元素已从 DOM 中移除时调用
function onAfterLeave(el) {}

// 仅在 v-show 过渡中可用
function onLeaveCancelled(el) {}

function transformKeyframesToSegments(keyframes) {
    // 确保关键帧按时间排序
    keyframes.sort((a, b) => a.time - b.time);

    // 存储转换后的段数据
    const segments = [];

    // 遍历关键帧，生成每段动画
    for (let i = 0; i < keyframes.length - 1; i++) {
        const current = keyframes[i];
        const next = keyframes[i + 1];

        // 构建每段动画数据
        const segment = {
            duration: next.time - current.time,
            data: {} // 用于存放除了 duration 以外的所有字段
        };

        // 动态处理所有字段，支持扩展
        Object.keys(current).forEach((key) => {
            if (key !== "time") {
                // 将字段存入 data 中，格式为 [起始值, 结束值]
                segment.data[key] = [current[key], next[key]];
            }
        });

        segments.push(segment);
    }

    return segments;
}
var playingAnimation = null;
function playAnimation(actionId){
    if(!transItem.value){
      return
    }
      const sequence = [] as any
      
      let animAttr =  transformKeyframesToSegments(props.timelineData.actions[actionId].data.keyFrames)
      animAttr.forEach(function(element){
        sequence.push([transItem.value,element.data,
        { 
          "duration": element.duration,
          "autoplay": true,ease: "easeInOut",
         
        }
      ])
      })
      console.log(sequence)
      playingAnimation = animate(sequence,{delay:0})
      playingAnimation.then(() => {
        console.log('finish')
        playingAnimation= null;
      })
}

function transformKeyframesToSegmentsAtTime(keyframes) {
    // 确保关键帧按时间排序
    keyframes.sort((a, b) => a.time - b.time);

    // 存储转换后的段数据
    const segments = [];

    // 遍历关键帧，生成每段动画
    for (let i = 0; i < keyframes.length - 1; i++) {
        const current = keyframes[i];
        const next = keyframes[i + 1];

        // 构建每段动画数据
        const segment = {
            duration: [current.time,next.time],
            data: {} // 用于存放除了 duration 以外的所有字段
        };

        // 动态处理所有字段，支持扩展
        Object.keys(current).forEach((key) => {
            if (key !== "time") {
                // 将字段存入 data 中，格式为 [起始值, 结束值]
                segment.data[key] = [current[key], next[key]];
            }
        });

        segments.push(segment);
    }

    return segments;
}
function getInterpolatedValue(from, to, currentTime, startTime, duration, easingFunction) {
    // 计算进度并应用缓动函数
    const progress = Math.min(Math.max((currentTime - startTime) / duration, 0), 1);
    const easedProgress = easingFunction(progress); // 使用缓动函数

    return from + easedProgress * (to - from);
}

function applyAnimationAtTime(element, segments, currentTime, easing = "easeInOut") {
    
    // 获取缓动函数，如果没有传入，则使用默认的 "easeInOut"
    const easingFunction = easingFunctions[easing] || easingFunctions["easeInOut"];

    segments.forEach((segment) => {
        const { duration, data } = segment;
        
        // 确保时间点在段的持续时间内
        if (currentTime >= duration[0]&&currentTime <= duration[1]) {
            const newStyles = {};
            
            // 对每个属性进行插值计算
            Object.keys(data).forEach((key) => {
                const [from, to] = data[key];
                const interpolatedValue = getInterpolatedValue(from, to, currentTime, duration[0], duration[1]-duration[0], easingFunction);
                newStyles[key] = interpolatedValue;
            });

            // 将计算后的样式应用到元素
            for(var key in newStyles){
              
              list.value[curIdx.value][key] = newStyles[key]
            }
            // Object.assign(element, newStyles);
        }
    });
}
function setAnimationByTime(time,actionId){
  const segments = transformKeyframesToSegmentsAtTime(props.timelineData.actions[actionId].data.keyFrames);

  if(transItem.value){
    applyAnimationAtTime(transItem.value,segments,time)
    // emitter.emit(mittTypes.RENDERER.UPDATE_RENDER)
    // emitter.emit(mittTypes.RENDERER.UPDATE_VALUE)
  }
}
function stopAnimation(){
  if(playingAnimation){
    playingAnimation.stop();
  }
}

function setShowAnimation(val){
  console.log(props.timelineData.actions[0].data.title,val)
  showAnim.value = val
  switch(props.timelineData.actions[0].effectId){

    case componentTypes.FLOW_EDIT.IMAGE:
      list.value = sceneStore.currentFlowNode.imageList
      break;
    case componentTypes.FLOW_EDIT.VIDEO:
      list.value = sceneStore.currentFlowNode.videoList
      break;
    case componentTypes.FLOW_EDIT.ACTION:
      list.value = sceneStore.currentFlowNode.actionList
      break;
    case componentTypes.FLOW_EDIT.SVGANIM:
      list.value = sceneStore.currentFlowNode.svgAnimList
      break;
    }
  list.value.forEach((element,idx) => {
    if(element.id == props.timelineData.id){
      curIdx.value = idx
    }
  });
}

const curIdx = ref(null)
const list = ref(null)
onMounted(() => {
  // if(props.animation){
  //     const sequence = [] as any
  //     props.animation.forEach(element => {
  //         sequence.push([transItem.value,element.animAttri,element.animOption])
  //     });
  //     let animation = animate(sequence,props.animationOption)
  //     animation.then(() => {
  //       console.log('finish')
  //     })
  // }
  // console.log(props.timelineData.actions[0].effectId)
  emitter.on(mittTypes.RENDERER.UPDATE_RENDER,function(){
    if(sceneStore.currentFlowNode){
      let data ;
      switch(props.timelineData.actions[0].effectId){

        case componentTypes.FLOW_EDIT.IMAGE:
          list.value = sceneStore.currentFlowNode.imageList
          break;
        case componentTypes.FLOW_EDIT.VIDEO:
          list.value = sceneStore.currentFlowNode.videoList
          break;
        case componentTypes.FLOW_EDIT.ACTION:
          list.value = sceneStore.currentFlowNode.actionList
          break;
        case componentTypes.FLOW_EDIT.SVGANIM:
          list.value = sceneStore.currentFlowNode.svgAnimList
          break;
      }
      list.value.forEach((element,idx) => {
        if(element.id == props.timelineData.id){
          curIdx.value = idx
        }
      });
    }
  })
  
})
defineExpose({
  playAnimation,
  setAnimationByTime,
  stopAnimation,
  setShowAnimation,
  props
})
</script>
<script lang="ts">
export default {
name: 'Animation'
}
</script>
<style>
</style>